package com.dgut.lab.service;

import com.dgut.lab.entity.Answer;
import com.dgut.lab.entity.User;
import com.dgut.lab.mapper.UserRepository;
import com.dgut.lab.util.CommonUtil;
import com.mongodb.client.result.UpdateResult;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.ParseException;
import java.util.*;
import java.util.regex.Pattern;

@Service
public class UserService {
    @Resource
    private UserRepository userRepository;
    @Resource
    private MongoTemplate mongoTemplate;

    @Resource AnswerService answerService;

    public User addUser(User user) {
        return userRepository.insert(user);
    }

    public User saveUser(User user){
        return userRepository.save(user);
    }

    public User queryByUsername(String username) {
        return userRepository.findByUsername(username);
    }

//    public Page<User> queryAllByPage(int page, int rows) {
////        PageRequest pageRequest = PageRequest.of(page-1,rows);
////        return userRepository.findAll(pageRequest);
////    }

    public List<User> queryAllUsers(){
        return userRepository.findAllByRoleLike("STUDENT");
    }

    public boolean modifyUserBasic(User user) {
        Query query = new Query(Criteria.where("_id").is(user.getUsername()));
        Update update = new Update();
        if(user.getPassword()!=null)
            update.set("password",user.getPassword());
        if(user.getName()!=null)
            update.set("name",user.getName());
        if(user.getIdNumber()!=null)
            update.set("idNumber",user.getIdNumber());
        if(user.getPhone()!=null)
            update.set("phone",user.getPhone());
        if(user.getSchool()!=null)
            update.set("school",user.getSchool());
        if(user.getDepartment()!=null)
            update.set("department",user.getDepartment());
        if(user.getMajor()!=null)
            update.set("major",user.getMajor());
        if(user.getClazz()!=null)
            update.set("clazz",user.getClazz());
        UpdateResult updateResult = mongoTemplate.updateFirst(query, update, User.class);
        return updateResult.getModifiedCount()==1;
    }

    public boolean modifyUserStatus(User user){
        Query query = new Query(Criteria.where("_id").is(user.getUsername()));
        Update update = new Update();
        if(user.getEnabled()!=null)
            update.set("enabled",user.getEnabled());
        if(user.getAccountNonExpired()!=null)
            update.set("accountNonExpired",user.getAccountNonExpired());
        if(user.getAccountNonLocked()!=null)
            update.set("accountNonLocked",user.getAccountNonLocked());
        if(user.getCredentialsNonExpired()!=null)
            update.set("credentialsNonExpired",user.getCredentialsNonExpired());

        if(user.getLastCommitTime()!=null)
            update.set("lastCommitTime",user.getLastCommitTime());
        UpdateResult updateResult = mongoTemplate.updateFirst(query, update, User.class);
        return updateResult.getModifiedCount()==1;
    }


    public UpdateResult modifyUserPassoword() {
        Query query = new Query(Criteria.where("password").is(""));
        Update update = new Update().set("password",new BCryptPasswordEncoder().encode("123456789"));
        UpdateResult updateResult = mongoTemplate.updateMulti(query, update, User.class);
        return updateResult;
    }

    public List<User> getNoPassword(){
        Query query = new Query(Criteria.where("password").is(""));
        List<User> users = mongoTemplate.find(query, User.class);
        return users;
    }

//    public List<User> queryNoCommitByPage(int page,int rows) throws ParseException {
//        Sort.Order order=new Sort.Order(Sort.Direction.ASC, "username");
//        PageRequest pageRequest = PageRequest.of(page-1,rows,Sort.by(order));
//        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
//        String format = simpleDateFormat.format(new Date());
//        Date parse = simpleDateFormat.parse(format);
//        System.out.println("now:"+format);
//        System.out.println("now Time:"+parse);
//        Query query = new Query(
//                                Criteria.where("lastCommitTime").lt(parse));
//        query.with(pageRequest);
//        return mongoTemplate.find(query,User.class);
//    }

    //学号，姓名，学院，专业，地址，体温(lowTemperature,highTemperature)，日期区间（startDate,endDate）
    public List<User> queryUserByCondition(Map<String,Object> map,Integer page,Integer rows) throws ParseException {
        if(map!=null){
            // 问卷答案的查询
            Date startDate = null;
            Date endDate = null;
            if(map.get("startDate")!=null) {
                startDate  = CommonUtil.DateToDate(((Date) map.get("startDate")));
            }
            if(map.get("endDate")!=null) {
                endDate  = CommonUtil.DateToDate(((Date) map.get("endDate")));
            }
            List<Answer> answers = answerService.queryUserByCondition(
                    map.get("address") != null ? ((String) map.get("address")) : null,
                    map.get("lowTemperature") != null ? ((String) map.get("lowTemperature")) : null,
                    map.get("highTemperature") != null ? ((String) map.get("highTemperature")) : null,
                    startDate, endDate);
            Iterator<Answer> answerIterator = answers.iterator();
            Set<String> usernameSet = new HashSet<>();
            while(answerIterator.hasNext()){
                usernameSet.add(answerIterator.next().getUsername());
            }
            // 用户创建查询
            Criteria where = new Criteria();
            Pattern username = null;
            if(map.get("username")!=null)
                username = Pattern.compile(".*?" + CommonUtil.escapeExprSpecialWord((String) map.get("username")) + ".*");
            if(usernameSet.size()>0 && map.get("username")!=null){
                assert username != null;
                where.andOperator(
                        Criteria.where("_id").regex(username),
                        Criteria.where("_id").in(usernameSet));
            }
            else if(map.get("username")!=null)
                where.and("_id").regex(username);
            else if(usernameSet.size()>0)
                where.and("_id").in(usernameSet);

            Pattern name = null;
            if(map.get("name")!=null){
                name = Pattern.compile(".*?" + CommonUtil.escapeExprSpecialWord((String) map.get("name")) + ".*");
                where.and("name").regex(name);
            }



            Pattern department = null;
            if(map.get("department")!=null){
                department = Pattern.compile(".*?" + CommonUtil.escapeExprSpecialWord((String) map.get("department")) + ".*");
                where.and("department").regex(department);
            }

            Pattern major = null;
            if(map.get("major")!=null){
                major = Pattern.compile(".*?" + CommonUtil.escapeExprSpecialWord((String) map.get("major")) + ".*");
                where.and("major").regex(major);
            }

            Query query = new Query(where);
            PageRequest pageRequest = PageRequest.of(page-1, rows,
                    Sort.by(Sort.Order.asc("_id")));
            query.with(pageRequest);
            List<User> users = mongoTemplate.find(query, User.class);
            return users;
        }
        else
            return userRepository.findAll();

    }

//    public  List<User> queryUser(Map<String,Object> map){
//        Set<String> usernameSet = new HashSet<>();
//        usernameSet.add("2018414105");
//        usernameSet.add("2017414101");
//        Criteria criteria = new Criteria();
////        criteria.and("_id").in(usernameSet);
//        Pattern username = Pattern.compile(".*?" + CommonUtil.escapeExprSpecialWord((String) map.get("username")) + ".*");
////        usernameSet.stream().filter(s -> {s.contains(".*?" + CommonUtil.escapeExprSpecialWord((String) map.get("username")) + ".*");}).collect(Collectors.toSet());
//        criteria.andOperator(
//                Criteria.where("_id").regex(username),
//                Criteria.where("_id").in(usernameSet));
//        Query query = new Query(criteria).with(Sort.by(Sort.Order.asc("_id")));
//        System.out.println(query);
//        return mongoTemplate.find(query,User.class);
//    }

    public List<User> queryUnSign(Map<String,Object> map) throws ParseException {
        Criteria criteria = new Criteria();
        criteria.and("enabled").is(1);

        if(map.get("username")!=null) {
            Pattern username = null;
            username = Pattern.compile(".*?" + CommonUtil.escapeExprSpecialWord((String) map.get("username")) + ".*");
            criteria.and("_id").regex(username);
        }
        if(map.get("name")!=null){
            Pattern name = null;
            name = Pattern.compile(".*?" + CommonUtil.escapeExprSpecialWord((String) map.get("name")) + ".*");
            criteria.and("name").regex(name);
        }
        if(map.get("department")!=null){
            Pattern department = null;
            department = Pattern.compile(".*?" + CommonUtil.escapeExprSpecialWord((String) map.get("department")) + ".*");
            criteria.and("department").regex(department);
        }
        if(map.get("major")!=null) {
            Pattern major = null;
            major = Pattern.compile(".*?" + CommonUtil.escapeExprSpecialWord((String) map.get("major")) + ".*");
            criteria.and("major").regex(major);
        }

        Date date = CommonUtil.DateToDate(new Date());
        criteria.and("lastCommitTime").lte(date);

        Pattern role = Pattern.compile(CommonUtil.escapeExprSpecialWord("ADMIN"));
        criteria.and("role").is("STUDENT");

        Query query = new Query(criteria).with(Sort.by(
                Sort.Order.asc("_id"),
                Sort.Order.desc("lastCommitTime")
        ));
        query.fields().include("name","idNumber","phone","school","department","grade","major","clazz","lastCommitTime","enabled","role");
        return mongoTemplate.find(query,User.class);
    }
}
